/**
 * @TimerManager.as
 *
 * @author sodaChen mail:sujun10#21cn.com
 * @version 1.0
 * <br>Copyright (C), 2013 asFrame.com
 * <br>This program is protected by copyright laws.
 * <br>Program Name:ASFrame
 * <br>Date:2015-4-30
 */
package com.asframe.time
{
	import com.asframe.collections.maps.HashMap;
	import com.asframe.log.Log;
	import com.asframe.pattern.Singleton;
	import com.asframe.pool.FactoryObjectPool;
	import com.asframe.pool.ObjectPool;
	import com.asframe.pool.impl.TimerFactoryImpl;

	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * Timer的强化处理，一般情况不再需要使用Timer了。需要Timer的时候，直接通过TimerPlus来进行使用。
	 * 注意，该类的每次使用的方法，都是会是一个新的Timer，所以得根据实际需要使用该类。适用于不是大规模的timer方法。
	 * 如果大规模相同频率需要使用到timer的，请使用TimerMgr类
	 * 添加延迟效果有个bug，比如你用延迟来做循环，当一个延迟结束之后，回调函数，然后这个回调函数又添加一次延迟（很上一次是相同的函数）
	 * 那么就会出现bug。有3种解决方案：
	 * 1.作为存储的key不能用function作为唯一key，生成一个唯一的ID（AS3的setTimeOut本身也是这么做的）
	 * 2.处理函数单独引用出来，然后先执行清除自己的操作，再执行回调函数
	 * 3.扔到一下帧去处理回调函数
	 * @author sodaChen
	 * Date:2015-4-30
	 */
	public class TimerPlus extends Singleton
	{
		private static var instance:TimerPlus;

		/** timer对象池 **/
		private var timerPool			:FactoryObjectPool = new FactoryObjectPool(new TimerFactoryImpl(),20);
		/** 延迟函数数据的对象池 **/
		private var timerDataPool		:ObjectPool = new ObjectPool(TimerData,20);
		/** 利用timer做key存放数据 **/
		private var delayMap			:HashMap = new HashMap();
		/** 利用函数做key存放数据 **/
		private var delayFunMap		:HashMap = new HashMap();

		public function TimerPlus()
		{
			timerPool = new FactoryObjectPool(new TimerFactoryImpl(),20);
			timerDataPool = new ObjectPool(TimerData,50);
			delayMap = new HashMap();
			delayFunMap = new HashMap();
		}

		public static function getInstance():TimerPlus
		{
			if(instance == null)
				instance =  Singleton.getInstanceOrCreate(TimerPlus);

			return instance;
		}
		/**
		 * 添加一个Timer事件 ,后面可以增加回调函数的参数必须为数组
		 * @param delay 延迟毫秒数（间隔）
		 * @param repeatCount  触发次数
		 * @param timerFun 每次触发回调的函数
		 * @param completeFun 结束回调函数
		 * @param args 调函数时的参数（不定）timerFun和completeFun都会接受args这些参数
		 */
		public function addTimerParams(delay:int,repeatCount:int,timerFun:Function,completeFun:Function,args:Array):void
		{
			if(timerFun == null && completeFun == null)
				throw new Error("非法传入addTimerParams的参数，timerFun和completeFun不能同时为空");
			var timer:Timer = timerPool.borrowObject();
			timer.delay = delay;
			timer.repeatCount = repeatCount;

			var timerData:TimerData = timerDataPool.borrowObject();
			timerData.timerFun = timerFun;
			timerData.completeFun = completeFun;
			timerData.repeatCount = repeatCount;
			timerData.args = args;
			timerData.timer = timer;
			delayMap.put(timer,timerData);

			if(timerFun != null)
			{
				delayFunMap.put(timerFun,timerData);
				timer.addEventListener(TimerEvent.TIMER,onTimerEvent,false,0,true);
			}
			else
			{
				timer.addEventListener(TimerEvent.TIMER_COMPLETE,onCompleteEvent,false,0,true);
				delayFunMap.put(completeFun,timerData);
			}

			timer.start();
		}
		/**
		 * 增加一个延迟回调函数,后面可以随意增加回调函数的参数(只处理一次)
		 * 注意这里是以completeFun作为key的，如果重复设置多次，只有最后一次有效果
		 * @param delay 延迟毫秒数
		 * @param completeFun 结束回调函数
		 * @param args 回调函数时的参数（不定）
		 *
		 */
		public function addDelay(delay:int,completeFun:Function,...args):void
		{
			addTimerParams(delay,1,null,completeFun,args);
		}
		public function setTimerOut():Number
		{
			return 0;
		}
		/**
		 * 删除添加的延迟函数
		 * @param completeFun
		 *
		 */
		public function removeDelay(completeFun:Function):void
		{
			var timerData:TimerData = delayFunMap.remove(completeFun);
			if(timerData != null)
			{
				if(timerData.timerFun != null)
					timerData.timer.removeEventListener(TimerEvent.TIMER,onTimerEvent);

				if(timerData.completeFun != null)
					timerData.timer.removeEventListener(TimerEvent.TIMER_COMPLETE,onCompleteEvent);
				//返回对象池
				timerPool.returnObject(timerData.timer);
				timerData.clear();
				timerDataPool.returnObject(timerData);
			}
		}
		/**
		 * 添加一个Timer事件 ,后面可以随意增加回调函数的参数
		 * @param delay 延迟毫秒数（间隔）
		 * @param timerFun 每次触发回调的函数
		 * @param repeatCount  触发次数，默认是0
		 * @param completeFun 结束回调函数，默认为空
		 * @param args 调函数时的参数（不定）timerFun和completeFun都会接受args这些参数
		 *
		 */
		public function addTimer(delay:int,timerFun:Function,repeatCount:int = 0,completeFun:Function = null,...args):void
		{
			addTimerParams(delay,repeatCount,timerFun,completeFun,args);
		}
		/**
		 * 删除Timer，根据每次timer响应的函数
		 * @param timerFun
		 *
		 */
		public function removeTimer(timerFun:Function):void
		{
			removeDelay(timerFun);
		}

		private function onTimerEvent(evt:TimerEvent):void
		{
			var timer:Timer = evt.target as Timer;
			var timerData:TimerData = delayMap.get(timer);
			timerData.repeatCount--;

			if(timerData.args != null && timerData.args.length == 0)
				timerData.timerFun();
			else
				timerData.timerFun.apply(null,timerData.args);

			//timer心跳执行是否完成
			if(timer.repeatCount != 0 && timerData.repeatCount <= 0)
			{
				delayMap.remove(timer);
				callBack(timerData);
			}
		}
		private function onCompleteEvent(evt:TimerEvent):void
		{
			var timer:Timer = evt.target as Timer;

			var timerData:TimerData = delayMap.remove(timer);
			if(timerData != null)
			{
				callBack(timerData);
			}
			else
			{
				//理论上不会出现，如果出现，证明出bug了
				Log.error(TimerPlus,"TimerPlus出现Bug了，onCompleteEvent找不到DelayData");
			}
		}
		private function callBack(timerData:TimerData):void
		{
			var tempFun:Function = timerData.completeFun;
			var args:Array = timerData.args;
			//最后清除
			removeDelay(timerData.completeFun);
			//同时有，责不需要再触发TimerEvent.TIMER_COMPLETE事件了
			if(tempFun != null)
			{
				if(args != null && args.length == 0)
					tempFun();
				else
					tempFun.apply(null,args);
			}
			tempFun = null;
			args = null;
		}
	}
}